﻿using System.Collections;
using Basic.FormCollect.Model;
using Basic.FormDAL;
using Basic.FormModel.QueryColumn;
using Basic.FormModel.QueryGroup;
using Basic.FormRemoteModel;
using WeDonekRpc.CacheClient.Interface;
using WeDonekRpc.Helper;

namespace Basic.FormCollect.Extend
{
    internal class PhysicsQueryBodyCollect : IPhysicsQueryBodyCollect
    {
        private readonly IPhysicalQueryTableDAL _Table;

        private readonly IPhysicalQueryColumnDAL _Column;
        private readonly IPhysicalQueryGroupDAL _Group;
        private readonly ICacheController _Cache;

        public PhysicsQueryBodyCollect ( IPhysicalQueryTableDAL table,
            IPhysicalQueryColumnDAL column,
            IPhysicalQueryGroupDAL group,
            ICacheController cache )
        {
            this._Group = group;
            this._Table = table;
            this._Column = column;
            this._Cache = cache;
        }

        public PhysicsFormBody Get ( long formId )
        {
            string key = "PhyQueryBody_" + formId;
            if ( this._Cache.TryGet(key, out PhysicsFormBody body) )
            {
                return body;
            }
            body = this._Get(formId);
            _ = this._Cache.Set(key, body, DateTime.Now.AddHours(12));
            return body;
        }
        private PhysicsFormBody _Get ( long formId )
        {
            var tables = this._Table.Gets(a => a.FormId == formId, a => new
            {
                a.Id,
                a.TableName,
                a.Show,
                a.IsMainTable
            });
            PhysicsQueryColumn[] cols = this._Column.Gets<PhysicsQueryColumn>(a => a.FormId == formId);
            PhyQueryGroup[] groups = this._Group.Gets<PhyQueryGroup>(a => a.FormId == formId);
            var main = tables.Find(c => c.IsMainTable);
            PhysicsQueryTable[] list = tables.ConvertAll(c =>
            {
                PhysicsQueryColumn[] col = cols.FindAll(a => a.TableId == c.Id);
                PhyExtendCol[] extends = col.Convert(a => a.ShowMode != PhyColShowMode.Column && a.SourceCol.HasValue, a =>
                {
                    PhyExtendCol t = new PhyExtendCol
                    {
                        Mode = a.ShowMode,
                        Name = a.ColName,
                        Source = a.SourceCol.Value,
                        DictId = a.DictId
                    };
                    PhysicsQueryColumn sour = cols.Find(b => b.Id == a.SourceCol.Value);
                    t.ColName = sour.ColName;
                    t.DictId = sour.DictId;
                    if ( a.ColumnSet != null )
                    {
                        if ( a.ShowMode == PhyColShowMode.DictItem && a.ColumnSet.TryGetValue("Items", out object val) )
                        {
                            IList itemList = (IList)val;
                            t.Items = new Dictionary<string, string>();
                            foreach ( IDictionary<string, object> i in itemList )
                            {
                                object v = i["value"];
                                t.Items.Add(v == null ? null : Convert.ToString(v), Convert.ToString(i["text"]));
                            }
                        }
                    }
                    return t;
                });
                string[] names = c.IsMainTable ? col.Convert(a => a.ShowMode == PhyColShowMode.Column, a => a.ColName) : col.Convert(a => a.ShowMode == PhyColShowMode.Column, a => a.ColName);
                return new PhysicsQueryTable
                {
                    Id = c.Id,
                    TableName = c.TableName,
                    Show = c.Show,
                    ExtendCol = extends,
                    Groups = groups.FindAll(a => a.TableId == c.Id),
                    IsMainTable = c.IsMainTable,
                    ColName = names,
                    Column = col.ToDictionary(a => a.Id, a => a)
                };
            });
            return new PhysicsFormBody
            {
                Main = list.Find(c => c.IsMainTable),
                Children = list.FindAll(c => c.IsMainTable == false)
            };
        }

        public PhysicsQueryTable GetTable ( long tableId )
        {
            string key = "PhyQueryTable_" + tableId;
            if ( this._Cache.TryGet(key, out PhysicsQueryTable table) )
            {
                return table;
            }
            table = this._GetTable(tableId);
            _ = this._Cache.Set(key, table, DateTime.Now.AddHours(12));
            return table;
        }

        private PhysicsQueryTable _GetTable ( long tableId )
        {
            var table = this._Table.Get(tableId, a => new
            {
                a.Id,
                a.TableName,
                a.IsMainTable,
                a.Show
            });
            PhysicsQueryColumn[] cols = this._Column.Gets<PhysicsQueryColumn>(a => a.TableId == tableId);
            PhyExtendCol[] extends = cols.Convert(a => a.ShowMode != PhyColShowMode.Column && a.SourceCol.HasValue, a =>
            {
                PhyExtendCol t = new PhyExtendCol
                {
                    Mode = a.ShowMode,
                    Name = a.ColName,
                    Source = a.SourceCol.Value,
                    DictId = a.DictId
                };
                PhysicsQueryColumn sour = cols.Find(b => b.Id == a.SourceCol.Value);
                t.ColName = sour.ColName;
                t.DictId = sour.DictId;
                if ( a.ColumnSet != null )
                {
                    if ( a.ShowMode == PhyColShowMode.DictItem && a.ColumnSet.TryGetValue("Items", out object val) )
                    {
                        IList itemList = (IList)val;
                        t.Items = new Dictionary<string, string>();
                        foreach ( IDictionary<string, object> i in itemList )
                        {
                            object v = i["value"];
                            t.Items.Add(v == null ? string.Empty : Convert.ToString(v), Convert.ToString(i["text"]));
                        }
                    }
                }
                return t;
            });
            PhyQueryGroup[] groups = this._Group.Gets<PhyQueryGroup>(a => a.TableId == tableId);
            return new PhysicsQueryTable
            {
                Id = table.Id,
                TableName = table.TableName,
                Show = table.Show,
                Groups = groups,
                ColName = table.IsMainTable ? cols.Convert(a => a.ShowMode == PhyColShowMode.Column, a => a.ColName) : cols.Convert(a => a.ShowMode == PhyColShowMode.Column, a => a.ColName),
                Column = cols.ToDictionary(a => a.Id, a => a),
                ExtendCol = extends,
                IsMainTable = table.IsMainTable
            };
        }
    }
}
